﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using Telerik.WinControls;
using Telerik.WinControls.UI;
using Telerik.WinControls.UI.Docking;
using MySQLStudio.BusinessLogic;
using MySQLStudio.GUI.Controls;
using MySQLStudio.Common;
using MySQLStudio.GUI.Controls.Table;
using System.Collections.Specialized;
using MySQLStudio.Common.Data;
using MySQLStudio.GUI.Controls.StoreProcedure;

namespace MySQLStudio.GUI
{
    public partial class frmMain : RadForm
    {
        public delegate void AddDatabasesToTreeCallback(Host host, RadTreeNode hostNode);
        public delegate void AddHostNodeToTreeCallback(RadTreeNode hostNode, RadTreeView catalogTreeView);
        public delegate void UpdateStatusBarTextCallBack(RadStatusStrip executionStatusStrip);

        public frmMain()
        {
            InitializeComponent();

            InitializeCatalogPanel();

            InitializeWindowsPanel();

            InitializeToolsWindow();
        }

        private void InitializeToolsWindow()
        {
            toolWindow.Text = string.Empty;
            lblExecutionProgress.Text = "Ready";
        }

        /// <summary>
        /// Removes all scripts windows as no connection is available
        /// </summary>
        private void InitializeWindowsPanel()
        {
            DockWindow[] documentWindows = this.mainDock.DocumentManager.DocumentArray;
            if (documentWindows != null)
            {
                foreach (DockWindow documentWindow in documentWindows)
                {
                    documentWindow.Close();
                }
            }

            this.mainDock.DockWindowClosing += new DockWindowCancelEventHandler(mainDock_DockWindowClosing);
            this.mainDock.DockWindowAdded += new DockWindowEventHandler(mainDock_DockWindowAdded);
        }

        void mainDock_DockWindowAdded(object sender, DockWindowEventArgs e)
        {
            TableDockWindow tableDocWindow = e.DockWindow as TableDockWindow;

            if (tableDocWindow != null)
            {
                tableDocWindow.TableSaved += new EventHandler<TableSavedEventArgs>(tableWindow_TableSaved);
            }
        }

        void mainDock_DockWindowClosing(object sender, DockWindowCancelEventArgs e)
        {
            TableDockWindow tableDocWindow = e.DockWindow as TableDockWindow;

            if (tableDocWindow != null)
            {
                tableDocWindow.TableSaved -= new EventHandler<TableSavedEventArgs>(tableWindow_TableSaved);
            }
        }

        private void InitializeCatalogPanel()
        {
            
        }

        /// <summary>
        /// Run task to retrive list of databases
        /// </summary>
        private void AddHostToTreeView(Host host)
        {
            if (!IsConnectedToHost(host))
            {
                DatabasesExtractTaskState state = new DatabasesExtractTaskState();
                state.Host = host;
                state.CatalogTreeView = objectsExplorerTree;

                ThreadPool.QueueUserWorkItem(new WaitCallback(GenerateHostHierarchy), state);
                ThreadPool.QueueUserWorkItem(new WaitCallback(GetCollations), state.Host);
            }
        }

        /// <summary>
        /// Check if allready connected to specific host
        /// </summary>
        /// <param name="host"></param>
        /// <returns></returns>
        private bool IsConnectedToHost(Host host)
        {
            bool isConnectedHost = false;

            if (objectsExplorerTree.Nodes != null)
            {
                foreach (RadTreeNode node in objectsExplorerTree.Nodes)
                {
                    if (node.DataBoundItem != null && node.DataBoundItem is Host)
                    {
                        Host nodeHost = node.DataBoundItem as Host;
                        if (nodeHost.Hostname == host.Hostname)
                            isConnectedHost = true;
                    }
                }
            }

            return isConnectedHost;
        }

        private void GenerateHostHierarchy(Object objState)
        {
            try
            {
                if (objState != null)
                {
                    DatabasesExtractTaskState state = objState as DatabasesExtractTaskState;
                    Host connectedHost = state.Host;

                    if (state != null)
                    {
                        RadTreeView catalogTreeView = state.CatalogTreeView;

                        RadTreeNode hostNode = CreateTreeNode(connectedHost.Hostname,
                                                            (int)ObjectsExplorerTreeNodeType.Host,
                                                            (int)ObjectsExplorerTreeNodeImageType.Host);

                        hostNode.DataBoundItem = connectedHost;
                        hostNode.ContextMenu = hostContextMenu;
                        hostNode.Expand();

                        if (catalogTreeView.InvokeRequired)
                            catalogTreeView.Invoke(new AddHostNodeToTreeCallback(this.AddHostNodeToTreeView),
                                                   new object[] { hostNode, catalogTreeView });
                        else
                            AddHostNodeToTreeView(hostNode, catalogTreeView);

                        if (catalogTreeView.InvokeRequired)
                            catalogTreeView.Invoke(new AddDatabasesToTreeCallback(this.GenerateDatabasesNodes),
                                                        new object[] { connectedHost, hostNode });
                        else
                            GenerateDatabasesNodes(connectedHost, hostNode);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(MySQLStudio.Common.Logger.GetExceptionFullContent(ex));
            }
        }

        private void GetCollations(Object objState)
        {
            try
            {
                if (objState != null)
                {
                    Host connectionContext = (Host)objState;
                    StringCollection collations = CollationController.GetCollations(connectionContext.ConnectionString);
                    Collations.ServerCollations = collations;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(MySQLStudio.Common.Logger.GetExceptionFullContent(ex));
            }
        }


        private void AddHostNodeToTreeView(RadTreeNode hostNode, RadTreeView catalogTreeView)
        {
            catalogTreeView.Nodes.Add(hostNode);
            catalogTreeView.SelectedNode = hostNode;
        }

        /// <summary>
        /// Extracts databases list and generates database nodes
        /// </summary>
        /// <param name="host"></param>
        /// <param name="hostNode"></param>
        private void GenerateDatabasesNodes(Host host, RadTreeNode hostNode)
        {
            List<Database> lstDatabases = DatabaseController.GetDatabases(host.ConnectionString);

            foreach (MySQLStudio.BusinessLogic.Database database in lstDatabases)
            {
                RadTreeNode databaseNode = CreateTreeNode(database.Name,
                                                        (int)ObjectsExplorerTreeNodeType.Database,
                                                        (int)ObjectsExplorerTreeNodeImageType.Database);


                databaseNode.Name = database.Name;
                databaseNode.DataBoundItem = database;
                databaseNode.ContextMenu = databaseContextMenu;

                // add nodes for  Tables, Views, Stored Procedures
                RadTreeNode tablesNode = CreateTreeNode("Tables",
                        (int)ObjectsExplorerTreeNodeType.TablesFolder,
                        (int)ObjectsExplorerTreeNodeImageType.TablesFolder);
                tablesNode.ContextMenu = tablesNodeContextMenu;

                RadTreeNode viewsNode = CreateTreeNode("Views",
                        (int)ObjectsExplorerTreeNodeType.ViewsFolder,
                        (int)ObjectsExplorerTreeNodeImageType.ViewsFolder);
                viewsNode.ContextMenu = viewParentNodeContextMenu;


                RadTreeNode routinesNode = CreateTreeNode("Stored Procedures",
                        (int)ObjectsExplorerTreeNodeType.StoredProceduresFolder,
                        (int)ObjectsExplorerTreeNodeImageType.StoredProceduresFolder);

                StoredProceduresFolder storedProceduresFolder = new StoredProceduresFolder();
                storedProceduresFolder.Populated = false;
                routinesNode.DataBoundItem = storedProceduresFolder;

                routinesNode.ContextMenu = routinesNodeContextMenu;

                databaseNode.Nodes.Add(tablesNode);
                databaseNode.Nodes.Add(viewsNode);
                databaseNode.Nodes.Add(routinesNode);

                hostNode.Nodes.Add(databaseNode);
            }
        }


        private void GenerateDatabasesDropDown(Host host, RadComboBox ddlDatabases, List<Database> lstDatabases)
        {
            Connect();
        }

        private ConnectToHost Connect()
        {
            ConnectToHost connectToHost = new ConnectToHost();
            connectToHost.ShowDialog(this);

            return connectToHost;
        }
        /// <summary>
        /// This event is being fired when node is being loaded on demand
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void objectsExplorerTree_NodeExpandedChanged(object sender, RadTreeViewEventArgs e)
        {
            Host host = null;
            Database database = null;

            RadTreeNode node = e.Node;
            if (node.Tag != null)
            {
                ObjectsExplorerTreeNodeType nodeType = (ObjectsExplorerTreeNodeType)node.Tag;

                switch (nodeType)
                {
                    case ObjectsExplorerTreeNodeType.StoredProceduresFolder:

                        StoredProceduresFolder storedProceduresFolder = node.DataBoundItem as StoredProceduresFolder;

                        if (storedProceduresFolder != null)
                        {
                            if (!storedProceduresFolder.Populated)
                            {
                                // extract  host and database context
                                GetHostAndDatabaseContext(node, out host, out database);

                                List<StoredProcedure> lstStoredProcedures = RoutinesController.GetStoredProcedures(host.ConnectionString, database.Name);

                                if (lstStoredProcedures != null)
                                {
                                    foreach (StoredProcedure sp in lstStoredProcedures)
                                    {
                                        RadTreeNode spNode = CreateTreeNode(sp.Name,
                                                                        (int)ObjectsExplorerTreeNodeType.StoredProcedure,
                                                                        (int)ObjectsExplorerTreeNodeImageType.StoredProcedure);
                                        spNode.Expanded = false;
                                        spNode.ContextMenu = routineNodeContextMenu;
                                        spNode.DataBoundItem = sp;
                                        spNode.LoadedOnDemand = true;
                                        node.Nodes.Add(spNode);
                                    }
                                }

                                storedProceduresFolder.Populated = true;
                            }
                        }

                        break;
                    case ObjectsExplorerTreeNodeType.ViewsFolder:
                        if (e.Node.Nodes.Count == 0)
                        {
                            // extract  host and database context
                            GetHostAndDatabaseContext(node, out host, out database);

                            List<MySQLStudio.BusinessLogic.View> lstViews = ViewController.GetViewsInDataBase(host.ConnectionString, database.Name);

                            if (lstViews != null)
                            {
                                //////////////////////////////////////////////////////////////////////////
                                //code clear node from old data to prevent 
                                //replication of data in node,may be change to something more effective
                                //////////////////////////////////////////////////////////////////////////
                                if (lstViews.Count > 0)
                                {
                                    for (int i = node.Nodes.Count - 1; i >= 0; i--)
                                    {
                                        node.Nodes.RemoveAt(i);
                                    }
                                }
                                foreach (MySQLStudio.BusinessLogic.View v in lstViews)
                                {
                                    RadTreeNode viewNode = CreateTreeNode(v.Name,
                                                                        (int)ObjectsExplorerTreeNodeType.View,
                                                                        (int)ObjectsExplorerTreeNodeImageType.View);
                                    viewNode.Expanded = false;
                                    viewNode.ContextMenu = viewNodeContextMenu;
                           
                                    viewNode.DataBoundItem = v;
                                  
                                    node.Nodes.Add(viewNode);
                                }
                            }
                        }
                        break;
                    case ObjectsExplorerTreeNodeType.TablesFolder:
                        if (e.Node.Nodes.Count == 0)
                        {
                            this.FillTables(e.Node);
                        }
                        break;
                    case ObjectsExplorerTreeNodeType.View:
                    case ObjectsExplorerTreeNodeType.Table:
                        if (node.Nodes.Count == 0)
                        {
                            IColumnsContainer container = (IColumnsContainer)node.DataBoundItem;
                            int count = container.Columns.Count;

                            for (int indx = 0; indx < count; indx++)
                            {
                                RadTreeNode columnNode = CreateTreeNode(container.Columns[indx].Name,
                                        (int)ObjectsExplorerTreeNodeType.Column,
                                        (int)ObjectsExplorerTreeNodeImageType.Column);

                                columnNode.LoadedOnDemand = true;
                                columnNode.DataBoundItem = container.Columns[indx];

                                if (container is Table)
                                {
                                    columnNode.ContextMenu = columnNodeContextMenu;
                                    columnNode.PropertyChanged += new PropertyChangedEventHandler(columnNode_PropertyChanged);
                                }

                                node.Nodes.Add(columnNode);
                            }
                        }
                        break;
                }

            }
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        private void GetTreeViewSelectedHostAndDatabaseNodes(RadTreeNode node, out RadTreeNode hostNode, out RadTreeNode databaseNode)
        {
            databaseNode = null;
            hostNode = null;
            ObjectsExplorerTreeNodeType nodeType;

            while (node != null)
            {
                nodeType = (ObjectsExplorerTreeNodeType)node.Tag;
                switch (nodeType)
                {
                    case ObjectsExplorerTreeNodeType.Database:
                        databaseNode = node;
                        break;
                    case ObjectsExplorerTreeNodeType.Host:
                        hostNode = node;
                        break;
                }
                node = node.Parent;
            }
        }

        /// <summary>
        /// Event handler for "Alter Routine" 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void alterRoutine_Click(object sender, EventArgs e)
        {
            Host host = null;
            Database database = null;

            try
            {
                RadTreeNode selectedRoutineNode = objectsExplorerTree.SelectedNode;
                if (selectedRoutineNode != null)
                {
                    ObjectsExplorerTreeNodeType nodeType = (ObjectsExplorerTreeNodeType)selectedRoutineNode.Tag;

                    if (nodeType == ObjectsExplorerTreeNodeType.StoredProcedure)
                    {
                        GetHostAndDatabaseContext(selectedRoutineNode, out host, out database);

                        RoutineActivitiesScriptWindow scriptWindow = new RoutineActivitiesScriptWindow(host, database);
                        scriptWindow.StoredProcedure = selectedRoutineNode.DataBoundItem as StoredProcedure;
                        scriptWindow.AlterRoutineStatement();

                        mainDock.AddDocument(scriptWindow);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(MySQLStudio.Common.Logger.GetExceptionFullContent(ex));
            }
        }

        /// <summary>
        /// Event Handler for "Create Routine"
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void createRoutine_Click(object sender, EventArgs e)
        {
            Host host = null;
            Database database = null;

            RadTreeNode node = objectsExplorerTree.SelectedNode;
            if (node != null)
            {
                GetHostAndDatabaseContext(node, out host, out database);

                RoutineActivitiesScriptWindow scriptWindow = new RoutineActivitiesScriptWindow(host, database);
                scriptWindow.CreateNewRoutineStatement();

                mainDock.AddDocument(scriptWindow);
            }
        }


        /// <summary>
        /// Refresh Routines "Click" event handler        
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void refreshRoutines_Click(object sender, EventArgs e)
        {
            Host host = null;
            Database database = null;

            try
            {
                RadTreeNode routinesNode = objectsExplorerTree.SelectedNode;
                if (routinesNode != null)
                {
                    StoredProceduresFolder storedProceduresFolder = routinesNode.DataBoundItem as StoredProceduresFolder;

                    // extact host and database context
                    GetHostAndDatabaseContext(routinesNode, out host, out database);

                    List<StoredProcedure> lstProcedures = RoutinesController.GetStoredProcedures(host.ConnectionString, database.Name);

                    // clear stored procedures nodes                    
                    routinesNode.Nodes.Clear();

                    if (lstProcedures != null)
                    {
                        foreach (StoredProcedure procedure in lstProcedures)
                        {
                            RadTreeNode spNode = CreateTreeNode(procedure.Name,
                                                                (int)ObjectsExplorerTreeNodeType.StoredProcedure,
                                                                (int)ObjectsExplorerTreeNodeImageType.StoredProcedure);
                            spNode.Expanded = true;
                            spNode.ContextMenu = routineNodeContextMenu;
                            spNode.DataBoundItem = procedure;

                            routinesNode.Nodes.Add(spNode);
                        }
                    }

                    if (storedProceduresFolder != null)
                        storedProceduresFolder.Populated = true;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(MySQLStudio.Common.Logger.GetExceptionFullContent(ex));
            }
        }

        /// <summary>
        /// Delete Routine "Click" event handler
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void deleteRoutine_Click(object sender, EventArgs e)
        {
            Host host = null;
            Database database = null;

            try
            {
                RadTreeNode routineNode = objectsExplorerTree.SelectedNode;
                if (routineNode != null)
                {
                    // extact host and database context
                    GetHostAndDatabaseContext(routineNode, out host, out database);

                    StoredProcedure storedProcedure = routineNode.DataBoundItem as StoredProcedure;
                    if (storedProcedure != null)
                    {
                        storedProcedure.Delete(host.ConnectionString);

                        routineNode.Parent.Nodes.Remove(routineNode);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(MySQLStudio.Common.Logger.GetExceptionFullContent(ex));
            }
        }

        /// <summary>
        /// Event Handler for "Create View"
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void radCreateViewMenuItem_onClick(object sender, EventArgs e)
        {
            Host host = null;
            Database database = null;

            RadTreeNode node = objectsExplorerTree.SelectedNode;
            if (node != null)
            {
                GetHostAndDatabaseContext(node, out host, out database);
                ViewScriptWindow tabPanel = new ViewScriptWindow(host, database);

                tabPanel.TableSchema = node.Parent.Text;
                tabPanel.LoadNewViewTemplate();
                tabPanel.ScriptTextBox.Dock = DockStyle.Fill;
                mainDock.AddDocument(tabPanel);

            }
        }


        private void AlterViewMenuItem_onClick(object sender, EventArgs e)
        {
            Host host = null;
            Database database = null;

            RadTreeNode node = objectsExplorerTree.SelectedNode;
            if (node != null)
            {
                GetHostAndDatabaseContext(node, out host, out database);

                ViewScriptWindow tabPanel = new ViewScriptWindow(host, database);

                tabPanel.TableSchema = node.Parent.Text;
                tabPanel.LoadAlterView(node.Parent.Parent.Text, node.Name);
                mainDock.AddDocument(tabPanel);
            }

        }

        private void DropViewMenuItem_onClick(object sender, EventArgs e)
        {
            RadTreeNode node = objectsExplorerTree.SelectedNode;
            try
            {
                String viewName = node.Parent.Parent.Text + "." + node.Text;
                DialogResult result = MessageBox.Show(
                    InfoMessages.GetString(InfoMessages.Action_Do_you_want_to_do,
                                            InformationSchemaHelper.GetViewDropStatementCommand(viewName)),
                                            InformationSchemaHelper.GetViewDropStatementCommand(String.Empty),
                                            MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation);

                if (result == DialogResult.OK)
                {
                    Host host = null;
                    Database database = null;
                    GetHostAndDatabaseContext(node, out host, out database);

                    SqlExecutionContext sqlExecutionContext = new SqlExecutionContext();
                    sqlExecutionContext.Hostname = host.Hostname;
                    sqlExecutionContext.PortNumber = host.PortNumber;
                    sqlExecutionContext.Username = host.Username;
                    sqlExecutionContext.Password = host.Password;
                    sqlExecutionContext.Database = database.Name;
                    sqlExecutionContext.SqlStatement = InformationSchemaHelper.GetViewDropStatementCommand(viewName);

                    SqlExecutionResult executionResult = SqlExecutionController.ExecuteSqlStatement(sqlExecutionContext);

                    if (executionResult != null)
                        FillResultsTable(executionResult, resultsWindow);

                    node.Remove();
                }

            }
            catch (System.Exception ex)
            {
                MessageBox.Show(MySQLStudio.Common.Logger.GetExceptionFullContent(ex));
            }

        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        private void GetHostAndDatabaseContext(RadTreeNode node, out Host hostContext, out Database databaseContext)
        {
            databaseContext = null;
            hostContext = null;

            if (node != null)
            {
                while (node.Parent != null)
                {
                    ObjectsExplorerTreeNodeType nodeType = (ObjectsExplorerTreeNodeType)node.Tag;

                    if (nodeType == ObjectsExplorerTreeNodeType.Database)
                    {
                        databaseContext = node.DataBoundItem as Database;
                        if (node.Parent != null)
                        {
                            RadTreeNode hostNode = node.Parent;
                            nodeType = (ObjectsExplorerTreeNodeType)hostNode.Tag;
                            if (nodeType == ObjectsExplorerTreeNodeType.Host)
                                hostContext = hostNode.DataBoundItem as Host;
                        }
                        break;
                    }
                    else
                        node = node.Parent;
                }
            }
        }

        private RadTreeNode CreateTreeNode(String name, int tag, int imageIndx)
        {
            RadTreeNode node = new RadTreeNode(name);
            node.Name = name;
            node.Tag = tag;
            node.ImageIndex = imageIndx;

            return node;
        }


        /// <summary>
        /// "New Script window" click event handler
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void imgNewScriptWindow_Click(object sender, EventArgs e)
        {
            ScriptWindow scriptWindow = GetScriptWindow();
            if (scriptWindow != null)
            {
                scriptWindow.Text = string.Format("script{0} on {1}.{2}", (mainDock.DockWindows.Count + 1).ToString(),
                                                                          scriptWindow.Database != null ? scriptWindow.Database.Name : string.Empty,
                                                                          scriptWindow.Host != null ? scriptWindow.Host.Hostname : string.Empty);
                mainDock.AddDocument(scriptWindow);
            }
            else
                MessageBox.Show(ErrorMessages.ScriptTabFailedToOpen, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }


        private void imgDatabaseConnections_Click(object sender, EventArgs e)
        {
            ConnectToHost connectToHost = Connect();

            if (connectToHost.DialogResult == DialogResult.OK)
            {
                //reconnectToServerMenuItem.Enabled = true;
                AddHostToTreeView(connectToHost.Host);
            }
        }

        private void imgExecuteSQL_Click(object sender, EventArgs e)
        {
            ScriptWindow activeScriptWindow = mainDock.DocumentManager.ActiveDocument as ScriptWindow;
            if (activeScriptWindow != null)
            {
                if (activeScriptWindow.Controls.Count > 0)
                {
                    //SyntaxHighlightingTextBox sqlTextBox = activeScriptWindow.Controls[0] as SyntaxHighlightingTextBox;
                    if (activeScriptWindow.SqlStatement != null)
                    {
                        SqlExecutionContext sqlExecutionContext = new SqlExecutionContext();
                        sqlExecutionContext.Hostname = activeScriptWindow.Host.Hostname;
                        sqlExecutionContext.PortNumber = activeScriptWindow.Host.PortNumber;
                        sqlExecutionContext.Username = activeScriptWindow.Host.Username;
                        sqlExecutionContext.Password = activeScriptWindow.Host.Password;
                        sqlExecutionContext.Database = activeScriptWindow.Database.Name;
                        sqlExecutionContext.SqlStatement = activeScriptWindow.SqlStatement;

                        ThreadPool.QueueUserWorkItem(new WaitCallback(ExecuteSqlStatement), sqlExecutionContext);                       
                    }
                }
            }
            else
                MessageBox.Show(ErrorMessages.ExecuteSqlNoStatementToExecute, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }


        private void ExecuteSqlStatement(object sqlExecutionContextObj)
        {
            if (sqlExecutionContextObj != null && sqlExecutionContextObj is SqlExecutionContext)
            {
                SqlExecutionContext sqlExecutionContext = sqlExecutionContextObj as SqlExecutionContext;

                // update status bar 
                if (executionStatusStrip.InvokeRequired)
                    executionStatusStrip.Invoke((MethodInvoker)delegate
                                                {
                                                    lblExecutionProgress.Text = "Executing...";
                                                });
                else
                    lblExecutionProgress.Text = "Executing...";
                        
               

                SqlExecutionResult executionResult = SqlExecutionController.ExecuteSqlStatement(sqlExecutionContext);

                if (executionResult != null)
                    resultsWindow.Invoke((MethodInvoker)delegate
                        {
                            FillResultsTable(executionResult, resultsWindow);
                        }
                );

                // update status bar 
                if (executionStatusStrip.InvokeRequired)
                    executionStatusStrip.Invoke((MethodInvoker)delegate
                    {
                        lblExecutionProgress.Text = "Ready";
                    });
                else
                    lblExecutionProgress.Text = "Ready";

            }
        }

        private void UpdateStatusBarText(RadStatusStrip executionStatusStrip)
        {
            lblExecutionProgress.Text = "Executing ...";                
        }

        protected void mainDoc_ActiveWindowChanged(object sender, DockWindowEventArgs e)
        {

        }


        private void createTableMenuItem_Click(object sender, EventArgs e)
        {
            Host host = null;
            Database database = null;
            RadTreeNode node = objectsExplorerTree.SelectedNode;

            GetHostAndDatabaseContext(node, out host, out database);

            TableDockWindow newTable = new TableDockWindow(host, database, null);
            addNewTab("Table", newTable, true);            
        }


        /// <summary>
        /// function add new Tab for dockwindow
        /// </summary>
        private void addNewTab(String tabTitle, DockWindow value, bool addCountToTitle)
        {

            String title = tabTitle;
            if (addCountToTitle)
                title += (mainDock.DocumentManager.DocumentArray.Length + 1).ToString();

            mainDock.AddDocument(value);
            mainDock.ActivateWindow(value);            
        }

        private void refreshTablesMenuItem_Click(object sender, EventArgs e)
        {
            RadTreeNode tablesNode = objectsExplorerTree.SelectedNode;

            if (tablesNode != null)
            {
                tablesNode.Nodes.Clear();

                this.FillTables(tablesNode);
            }
        }

        private void FillTables(RadTreeNode node)
        {
            Host host = null;
            Database database = null;

            GetHostAndDatabaseContext(node, out host, out database);

            List<Table> lstTables = TablesController.GetTablesInDatabase(host.ConnectionString, database.Name);

            if (lstTables != null)
            {
                //////////////////////////////////////////////////////////////////////////
                //code clear node from old data to prevent 
                //replication of data in node,may be change to something more effective
                //////////////////////////////////////////////////////////////////////////
                foreach (Table table in lstTables)
                {
                    RadTreeNode tableNode = CreateTreeNode(table.Name,
                                                        (int)ObjectsExplorerTreeNodeType.Table,
                                                        (int)ObjectsExplorerTreeNodeImageType.Table);
                    tableNode.Expanded = false;
                    tableNode.DataBoundItem = table;
                    tableNode.PropertyChanged += new PropertyChangedEventHandler(tableNode_PropertyChanged);

                    tableNode.ContextMenu = tableNodeContextMenu;
                    node.Nodes.Add(tableNode);
                }
            }
        }

        void tableNode_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "Text")
            {
                Host host = null;
                Database database = null;
                RadTreeNode tableNode = (RadTreeNode)sender;

                GetHostAndDatabaseContext(tableNode, out host, out database);

                Table table = (Table)tableNode.DataBoundItem;

                try
                {
                    table.Rename(host, database, tableNode.Text);
                }
                catch (ApplicationException ex)
                {
                    tableNode.PropertyChanged -= new PropertyChangedEventHandler(tableNode_PropertyChanged);
                    tableNode.Text = table.Name;
                    tableNode.PropertyChanged += new PropertyChangedEventHandler(tableNode_PropertyChanged);

                    MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        void columnNode_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "Text")
            {
                Host host = null;
                Database database = null;
                RadTreeNode columnNode = (RadTreeNode)sender;

                GetHostAndDatabaseContext(columnNode, out host, out database);

                Column column = (Column)columnNode.DataBoundItem;

                try
                {
                    column.Rename(host, database, columnNode.Text);
                }
                catch (ApplicationException ex)
                {
                    columnNode.PropertyChanged -= new PropertyChangedEventHandler(columnNode_PropertyChanged);
                    columnNode.Text = column.Name;
                    columnNode.PropertyChanged += new PropertyChangedEventHandler(columnNode_PropertyChanged);

                    MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        private void radMenuItem9_Click(object sender, EventArgs e)
        {
            RadTreeNode node = objectsExplorerTree.Nodes.ElementAt(0);
            Host host = node.DataBoundItem as Host;

            for (int i = objectsExplorerTree.Nodes.Count - 1; i >= 0; i--)
            {
                objectsExplorerTree.Nodes.RemoveAt(i);
            }

            AddHostToTreeView(host);
        }

        private void designTableMenuItem_Click(object sender, EventArgs e)
        {
            Host host = null;
            Database database = null;
            RadTreeNode node = objectsExplorerTree.SelectedNode;

            if (node != null)
            {
                GetHostAndDatabaseContext(node, out host, out database);

                Table table = (Table)(node.DataBoundItem as ICloneable).Clone();

                TableDockWindow tableWindow = mainDock.DockWindows.OfType<TableDockWindow>()
                    .FirstOrDefault(win => win.Table.Name.Equals(table.Name, StringComparison.InvariantCultureIgnoreCase)
                        && win.Host.Hostname.Equals(host.Hostname, StringComparison.InvariantCultureIgnoreCase)
                        && win.Database.Name.Equals(database.Name, StringComparison.InvariantCultureIgnoreCase));

                if (tableWindow == null)
                {
                    tableWindow = new TableDockWindow(host, database, table);

                    mainDock.AddDocument(tableWindow);
                }
                else
                {
                    mainDock.ActivateWindow(tableWindow);
                }               
            }
        }

        void tableWindow_TableSaved(object sender, TableSavedEventArgs e)
        {
            if (this.objectsExplorerTree != null)
            {
                RadTreeNode hostNode = this.objectsExplorerTree.Nodes
                    .FirstOrDefault(h => h.Text.Equals(e.Host, StringComparison.InvariantCultureIgnoreCase));

                if (hostNode != null)
                {
                    RadTreeNode databaseNode = hostNode.Nodes
                        .FirstOrDefault(d => d.Text.Equals(e.Database, StringComparison.InvariantCultureIgnoreCase));

                    if (databaseNode != null)
                    {
                        RadTreeNode tablesNode = databaseNode.Nodes
                            .FirstOrDefault(tf => tf.Text.Equals("Tables", StringComparison.InvariantCultureIgnoreCase));

                        if (tablesNode != null)
                        {
                            tablesNode.Nodes.Clear();

                            this.FillTables(tablesNode);
                        }
                    }
                }
            } 
        }

        private void renameTableMenuItem_Click(object sender, EventArgs e)
        {
            RadTreeNode node = objectsExplorerTree.SelectedNode;
            node.BeginEdit();
        }
        
        private void renameColumnMenuItem_Click(object sender, EventArgs e)
        {
            RadTreeNode node = objectsExplorerTree.SelectedNode;
            node.BeginEdit();
        }

        private void deleteTableMenuItem_Click(object sender, EventArgs e)
        {
            Host host = null;
            Database database = null;
            RadTreeNode node = objectsExplorerTree.SelectedNode;

            GetHostAndDatabaseContext(node, out host, out database);

            Table table = (Table)node.DataBoundItem;

            try
            {
                table.Delete(host, database);
                node.Remove();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// Builds a results grid in Tools Window
        /// </summary>
        /// <param name="executionResult"></param>
        /// <param name="resultsWindow"></param>
        private void FillResultsTable(SqlExecutionResult executionResult, ToolWindow resultsWindow)
        {
            executionResultsTab.ContentPanel.Controls.Clear();
            executionMessagesTab.ContentPanel.Controls.Clear();

            if (executionResult.ResultsTable != null)
            {
                // create GridView and show the results
                RadGridView resultsGrid = new RadGridView();
                resultsGrid.AutoGenerateHierarchy = true;                
                resultsGrid.ReadOnly = true;
                resultsGrid.AllowDrop = false;                 
                resultsGrid.DataSource = executionResult.ResultsTable;
                resultsGrid.Dock = DockStyle.Fill;

                executionResultsTab.ContentPanel.Controls.Add(resultsGrid);               
            }

            if (executionResult.Messages != null)
            {
                RadTextBox txtMessages = new RadTextBox();
                txtMessages.Multiline = true;
                txtMessages.MaxLength = int.MaxValue;
                txtMessages.Dock = DockStyle.Fill;

                txtMessages.Font = FontsInUse.ResultMessageFont;
                txtMessages.ForeColor = Color.Red;

                List<string> lstMessages = executionResult.Messages;
                 
                foreach (string message in lstMessages)
                {
                    txtMessages.Text += string.Format("{0}\n", message);
                }
                 
                executionMessagesTab.ContentPanel.Controls.Add(txtMessages);               
            }

            if (executionResult.DataRead)
                executionResultsTabStrip.SelectedTab = executionResultsTab;
            else
                executionResultsTabStrip.SelectedTab = executionMessagesTab;            
        }

        private void imgSaveSQL_Click(object sender, EventArgs e)
        {
            this.Save();
        }

        private void Save()
        {
            ScriptWindow activeWindow = mainDock.DocumentManager.ActiveDocument as ScriptWindow;
            TableDockWindow tableDockWindow = mainDock.DocumentManager.ActiveDocument as TableDockWindow;

            if (tableDockWindow != null && tableDockWindow.Controls.Count > 0
                && tableDockWindow.Controls[0] is TableControl)
            {
                TableControl tableControl = (TableControl)tableDockWindow.Controls[0];
                tableControl.Save();

                RadTreeNode node = this.objectsExplorerTree.Nodes["Tables"];
            }
        }


        private HostDatabaseSelection GetTreeViewSelectedHostAndDatabase()
        {
            HostDatabaseSelection hostAndDatabase = new HostDatabaseSelection();

            RadTreeNode hostNode, databaseNode;
            RadTreeNode selectedNode = objectsExplorerTree.SelectedNode;

            GetTreeViewSelectedHostAndDatabaseNodes(selectedNode, out hostNode, out databaseNode);

            if (hostNode != null)
                hostAndDatabase.Host = hostNode.DataBoundItem as Host;

            if (databaseNode != null)
                hostAndDatabase.Database = databaseNode.DataBoundItem as Database;

            return hostAndDatabase;
        }

        private ScriptWindow GetScriptWindow()
        {
            ScriptWindow scriptWindow = null;

            HostDatabaseSelection activeSelection = GetTreeViewSelectedHostAndDatabase();
            if (activeSelection.Host == null)
            {
                ConnectToHost connectToHost = Connect();

                if (connectToHost.DialogResult == DialogResult.OK)
                    activeSelection.Host = connectToHost.Host;
                else
                    return null;
            }

            if (activeSelection.Database != null)
                scriptWindow = new ScriptWindow(activeSelection.Host, activeSelection.Database);
            else
                scriptWindow = new ScriptWindow(activeSelection.Host, DatabaseController.GetDatabase(activeSelection.Host.ConnectionString,
                                                                                                     InformationSchemaHelper.INFORMATION_SCHEMA_TABLE));

            return scriptWindow;
        }



        private void dropDatabaseMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                RadTreeNode databaseNode = objectsExplorerTree.SelectedNode;

                if (databaseNode != null)
                {
                    ObjectsExplorerTreeNodeType nodeType = (ObjectsExplorerTreeNodeType)databaseNode.Tag;
                    if (nodeType == ObjectsExplorerTreeNodeType.Database)
                    {
                        Database database = databaseNode.DataBoundItem as Database;
                        if (database != null)
                        {
                            ScriptWindow scriptWindow = GetScriptWindow();
                            if (scriptWindow != null)
                            {
                                scriptWindow.Text = string.Format("script{0} on {1}.{2}", (mainDock.DockWindows.Count + 1).ToString(),
                                                                                          scriptWindow.Database != null ? scriptWindow.Database.Name : string.Empty,
                                                                                          scriptWindow.Host != null ? scriptWindow.Host.Hostname : string.Empty);
                                scriptWindow.SqlContent = InformationSchemaHelper.GetDropDatabseCommand(database.Name);
                                mainDock.AddDocument(scriptWindow);
                            }
                            else
                                MessageBox.Show(ErrorMessages.ScriptTabFailedToOpen, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ErrorMessages.ScriptTabFailedToOpen, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void createDatabaseMenuItem_Click(object sender, EventArgs e)
        {
            ScriptWindow scriptWindow = GetScriptWindow();
            if (scriptWindow != null)
            {
                scriptWindow.Text = string.Format("script{0} on {1}.{2}", (mainDock.DockWindows.Count + 1).ToString(),
                                                                          scriptWindow.Database != null ? scriptWindow.Database.Name : string.Empty,
                                                                          scriptWindow.Host != null ? scriptWindow.Host.Hostname : string.Empty);
                scriptWindow.SqlContent = InformationSchemaHelper.GetCreateDatabaseCommand();
                mainDock.AddDocument(scriptWindow);
            }
            else
                MessageBox.Show(ErrorMessages.ScriptTabFailedToOpen, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        private void refreshHostMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                RadTreeNode hostNode = objectsExplorerTree.SelectedNode;

                if (hostNode != null)
                {
                    ObjectsExplorerTreeNodeType nodeType = (ObjectsExplorerTreeNodeType)hostNode.Tag;
                    if (nodeType == ObjectsExplorerTreeNodeType.Host)
                    {
                        Host host = hostNode.DataBoundItem as Host;
                        if (host != null)
                        {
                            hostNode.Nodes.Clear();

                            GenerateDatabasesNodes(host, hostNode);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ErrorMessages.DatabasesListRefreshFailed, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void radMenuItemAbout_Click(object sender, EventArgs e)
        {
            About about = new About();
            about.ShowDialog(this);
        }

        private void newTabMenuItem_Click(object sender, EventArgs e)
        {
            imgNewScriptWindow_Click(sender, e);
        }       

        private void radMenuItem11_Click(object sender, EventArgs e)
        {
            refreshHostMenuItem_Click(sender, e);
        }

        private void ConnectMenuItem_Click(object sender, EventArgs e)
        {
            Connect();
        }

        private void ExitMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void DisConnectMenuItem_Click(object sender, EventArgs e)
        {
            if (objectsExplorerTree.Nodes != null)
            {

                RadTreeNode hostNode = objectsExplorerTree.SelectedNode;

                if (hostNode != null)
                {
                    ObjectsExplorerTreeNodeType nodeType = (ObjectsExplorerTreeNodeType)hostNode.Tag;
                    if (nodeType == ObjectsExplorerTreeNodeType.Host)
                    {

                        try
                        {
                            DialogResult result = MessageBox.Show(
                                 InfoMessages.GetString(InfoMessages.Action_Do_you_want_to_do,
                                                         "disconnect from " + hostNode.Name),
                                                         "Disconnect",
                                                         MessageBoxButtons.OKCancel,
                                                          MessageBoxIcon.Exclamation);

                            if (result == DialogResult.OK)
                            {
                                //disconnection action
                            }

                        }
                        catch (System.Exception ex)
                        {
                            MessageBox.Show(MySQLStudio.Common.Logger.GetExceptionFullContent(ex));
                        }
                    }
                }
            }
        }

        private void objectsExplorerTree_MouseDoubleClick(object sender, MouseEventArgs e)
        {

            if (objectsExplorerTree != null)
            {
                RadTreeNode selectedNode = objectsExplorerTree.SelectedNode;

                switch ((int)selectedNode.Tag)
                {
                    case (int)ObjectsExplorerTreeNodeType.View:
                    case (int)ObjectsExplorerTreeNodeType.StoredProcedure:
                    case (int)ObjectsExplorerTreeNodeType.Table:
                    case (int)ObjectsExplorerTreeNodeType.Column:
                        ScriptWindow activeScriptWindow = mainDock.DocumentManager.ActiveDocument as ScriptWindow;
                        if (activeScriptWindow != null)
                        {
                            if (activeScriptWindow.Controls.Count > 0)
                            {
                                activeScriptWindow.InsertText(" " + selectedNode.Name + " ");
                            }
                        }
                        break;
                }
            }

        }

        private void frmMain_Load(object sender, EventArgs e)
        {

        }

        private void scriptTableSelectMenuItem_Click(object sender, EventArgs e)
        {
            Host host = null;
            Database database = null;
            RadTreeNode node = objectsExplorerTree.SelectedNode;

            if (node != null)
            {
                GetHostAndDatabaseContext(node, out host, out database);

                Table table = node.DataBoundItem as Table;
                if (table != null)
                {
                    ScriptWindow scriptWindow = GetScriptWindow();
                    if (scriptWindow != null)
                    {
                        scriptWindow.Text = string.Format("script{0} on {1}.{2}", (mainDock.DockWindows.Count + 1).ToString(),
                                                                                  scriptWindow.Database != null ? scriptWindow.Database.Name : string.Empty,
                                                                                  scriptWindow.Host != null ? scriptWindow.Host.Hostname : string.Empty);
                        scriptWindow.SqlContent = table.GetSelectStatement();
                        mainDock.AddDocument(scriptWindow);
                    } 
                }
            }
        }

        private void scriptTableInsertMenuItem_Click(object sender, EventArgs e)
        {
            Host host = null;
            Database database = null;
            RadTreeNode node = objectsExplorerTree.SelectedNode;

            if (node != null)
            {
                GetHostAndDatabaseContext(node, out host, out database);

                Table table = node.DataBoundItem as Table;
                if (table != null)
                {
                    ScriptWindow scriptWindow = GetScriptWindow();
                    if (scriptWindow != null)
                    {
                        scriptWindow.Text = string.Format("script{0} on {1}.{2}", (mainDock.DockWindows.Count + 1).ToString(),
                                                                                  scriptWindow.Database != null ? scriptWindow.Database.Name : string.Empty,
                                                                                  scriptWindow.Host != null ? scriptWindow.Host.Hostname : string.Empty);
                        scriptWindow.SqlContent = table.GetInsertStatement();
                        mainDock.AddDocument(scriptWindow);
                    }
                }
            }
        }

        private void scriptViewSelectFromMenuItem_Click(object sender, EventArgs e)
        {
            Host host = null;
            Database database = null;
            RadTreeNode node = objectsExplorerTree.SelectedNode;

            if (node != null)
            {
                GetHostAndDatabaseContext(node, out host, out database);

                MySQLStudio.BusinessLogic.View view = node.DataBoundItem as MySQLStudio.BusinessLogic.View;
                if (view != null)
                {
                    ScriptWindow scriptWindow = GetScriptWindow();
                    if (scriptWindow != null)
                    {
                        scriptWindow.Text = string.Format("script{0} on {1}.{2}", (mainDock.DockWindows.Count + 1).ToString(),
                                                                                  scriptWindow.Database != null ? scriptWindow.Database.Name : string.Empty,
                                                                                  scriptWindow.Host != null ? scriptWindow.Host.Hostname : string.Empty);
                        scriptWindow.SqlContent = view.GetSelectStatement();
                        mainDock.AddDocument(scriptWindow);
                    }
                }
            }
        }
       
    }
}
